var g_s_regs = {};
var g_s_registered = {id:0};
var g_isie = null;
var defaultAlign = new Object();
defaultAlign["string"] = "left";
defaultAlign["link"] = "center";
defaultAlign["number"] = "right";
defaultAlign["boolean"] = "center";
defaultAlign["select"] = "center";
defaultAlign["undefined"] = "left";
defaultAlign["null"] = "left";
String.prototype.trim = function () {
	var reg = g_s_regs["(^\s*)|(\s*$)"];
	if(reg==undefined){
		reg = /(^\s*)|(\s*$)/g;
		g_s_regs["(^\s*)|(\s*$)"] = reg;
	}
	return this.replace(reg, "");
}

String.prototype.endWith = function(s){
	var p = this.lastIndexOf(s);
	if(p+s.length==this.length){
		return true;
	}else
		return false;
}

//****************************************************************
//* 功    能：计算字符串的长度(Unicode长度为2，非Unicode长度为1)
//*****************************************************************
String.prototype.asciiLen = function(){
    var intLength=0
    for (var i=0;i<this.length;i++){
        if ((this.charCodeAt(i) < 0) || (this.charCodeAt(i) > 255))
            intLength=intLength+2
        else
            intLength=intLength+1    
    }
    return intLength

}

Array.prototype.indexOf=function(o){
	for(var i=0;i<this.length;i++){
		if(this[i]==o)
			return i;
	}
	return-1;
};

Array.prototype.lastIndexOf=function(o){
	for(var i=this.length-1;i>=0;i--){
		if(this[i]==o)
			return i;
	}
	return-1;
};

Array.prototype.contains=function(o){
	return this.indexOf(o)!= -1;
};

Array.prototype.addAll=function(newArray){
	for(var i=0;i<newArray.length;i++){
		this.push(newArray[i]);
	}
}

Array.prototype.copy=function(o){
	return this.concat();
};

Array.prototype.insertAt=function(o,i){
	this.splice(i,0,o);
};

Array.prototype.insertBefore=function(o,o2){
	var i=this.indexOf(o2);
	if(i== -1)
		this.push(o);
	else
		this.splice(i,0,o);
};

Array.prototype.removeAt=function(i){
	this.splice(i,1);
};

Array.prototype.remove=function(o){
	var i=this.indexOf(o);
	if(i!= -1)
		this.splice(i,1);
};

Object.prototype.s$ = function(name,v,mode){
	var ns = null;
	if(typeof(name)==="string"){
		ns = name.split(".");
		if(mode==="number"){
			v = new Number(v);
		}else if(mode==="boolean"){
			if(v==="1")
				v = true;
			else if(v==="0")
				v = false;
		}else if(mode==="date"){
			return false;
		}
	}else if(name instanceof Array){
		ns = name;
	}else{
		alert("非法参数："+name);
		return false;
	}
	
	if(ns.length>1){
		var obj =this[ns[0]];
		if(obj===null || obj ===undefined){
			obj = new Object();
			this[ns[0]] = obj;
			ns.shift();
			obj.s$(ns,v,mode);
		}else{
			ns.shift();
			obj.s$(ns,v,mode);
		}
	}else{
		this[ns[0]] = v;
	}
}

Object.prototype.p$ = function(name,mode){
	var ns = null;
	if(typeof(name)==="string"){
		ns = name.split(".");
	}else if(name instanceof Array){
		ns = name;
	}else{
		alert("非法参数："+name);
		return;
	}
	if(ns.length>1){
		var obj =this[ns[0]];
		if(obj===null || obj ===undefined){
			return null;
		}else{
			ns.shift();
			return obj.p$(ns,mode);
		}
	}else{
		var v = this[ns[0]];
		if(v==null){
			if(mode!==undefined){
				if(mode==="number")
					v = 0;
				else if(mode==="boolean")
					v = false;
				else 
					v = "";
			}
		}
		return v;
	}
}

//数字格式化。format是格式，"#" 表示只保留整数，"#.00"表示保留两位小数，"#.00#" 表示保留至少两位小数,"#.0%"表示保留一位小数的百分数
Number.prototype.format = function(f){
	var n = this;
	f = f.trim();
	if(f==null)	f = "#.00";
	var isPercent = false;
	if(f.endWith("%")){
		isPercent = true;
		n = n*100;
		f = f.substring(0,f.length-1);
	}
	var v ;
	if(f=="#"){
		v = String(Math.round(n));
	}else{
		var c = 0;
		if(f.endWith("#")){
			c = f.length - 3;
			v  = ""+n;
		}else{
			c = f.length - 2;
			var p = Math.pow(10,c);
			var t = p * n;
			t = Math.round(t);
			v = String(t / p);
		}	
		if(c>0){
			if(v.indexOf(".")===-1){
				v = v+".0";
			}
			var p = v.indexOf(".")+1;
			if(v.length-p<c){
				var l = c-(v.length-p);
				for(var i = 0;i<l;i++){
					v = v+"0";
				}
			}
		}
	}
	if(isPercent===true){
		v = v+"%";
	}
	return v;
}

Function.prototype.getName = function(){
	var r = ""+this;
	var p = r.indexOf("{");
	r = r.substring(0,p);
	return r;
}

var SigmaUtil = {
	version:"1.0",
	$ : function(id){
		var dom = document.getElementById(id);
		return dom;
	},
	$$:function(e1,e2){
		if(e1 instanceof String){
			e1 = SigmaUtil.$(e1);
		}
		if(navigator.appVersion.indexOf("MSIE")!=-1){
			return e1.all(e2);
		}else{
			var cs =  e1.childNodes;
			var r = null;
			for(var i=0;i<cs.length;i++){
				var c = cs[i];
				if(e2===c.id ) r = c;
				else r = SigmaUtil.$$(c,e2);
				if(r!=null)	return r;
			}
			return null;
		}
	},

	isIE : function(){
		if(g_isie===null){
			if(navigator.appVersion.indexOf("MSIE")>=0){
				g_isie =  true;
			}else{
				g_isie = false;
			}
		}
		return g_isie;
	},
	
	register : function(obj){
		var rs = g_s_registered;
		if(obj.id!=null){
			rs[obj.id] = obj;
		}else{
			rs.id++;
			obj.id = rs.id;
			rs[obj.id] = obj;
		}
	},
	retrieve:function(objId){
		var rs = g_s_registered;
		return rs[objId];
	},

	closeLog :function(){
		window.slogClosed = true;
	},
	clearLog :function(){
		window._log_out.value = "";
	},
	log:function(s){
		if(window.slogClosed==true) return;
		if(window._log_out == null){
			var box = document.createElement("div");
			var tip = document.createElement("div");
			var out = null;
			box.style.width ="100%";
			tip.innerHTML = "隐藏日至";
			tip.onclick = function(){
				if(out.style.display == ""){
					out.style.display="none";
					tip.innerHTML = "显示日志";
				}else{
					out.style.display="";
					tip.innerHTML = "隐藏日志";
				}
			}
			out = document.createElement("textarea");
			out.style.width = "100%";
			out.style.height = "300px";
			box.appendChild(tip);
			box.appendChild(out);
			document.body.appendChild(box);
			window._log_out = out;
		}
		var fN = SigmaUtil.log.caller.getName();
		var t = new Date().toLocaleString();
		s = t + " " + ":" + s;
		window._log_out.value = window._log_out.value+s+"\n";
	}
}

function SigmaCell(row,col){
	this.row = row ;
	this.col = col;
	var oThis = this;
	this.name = col.name;
	this.paintEditor = function(td){
		var str = row.grid.getColumnEditor(col).paint(row.grid,row,col);
		td.innerHTML = str;
	}
	this.repaint = function(td){
		if(td==null) td = oThis.getElement();
		var str = row.grid.getColumnRender(col).paint(row.grid,row,col);
		var sb = new Array();
		var align = "center";
		if(col.align!=null)	align = col.align;
		else align = defaultAlign[col.mode];
		sb.push('<div style="text-align:'+align+';"');
		sb.push('>'+str);
		sb.push('</div>');
		td.innerHTML = sb.join("");
	}
	this.isRightColumn = function(){
		var cols = row.grid.leafCols;
		var index = cols.indexOf(col);
		if(index>=row.grid.context.locked)
			return true;
	}
	this.isReadonly = function(){
		if(col.formula!=null) return true; 	//表达式列是只读的
		if(col.readonly==null) return row.grid.context.readonly;
		else{
			var exp = "obj="+ col.readonly;
			exp = exp.replace(/p\$/ig,"row.rowData.p$");
			return eval(exp);
		}
	}
	this.getElement = function(){
		var trs = oThis.row.getElements();
		if(trs==null) return null;
		var trL = trs[0];
		var trR = trs[1];
		var tds  = [];
		tds.addAll(trL.cells);
		tds.addAll(trR.cells);
		for(var i=0;i<tds.length;i++){
			var td = tds[i];
			var s = td.id.split("@");
			if(s[2]==oThis.name)
				return td;
		}
		return null;
	}
	this.setValue = function(newData,evtTrigger){
		var rowData = oThis.row.rowData;
		var oldData = rowData.p$(oThis.name);
		var cell = oThis.getElement();
		if(cell == null) return;
		if(oldData!=newData){
			oThis.row.buf = null;
			//SigmaUtil.log("设置单元格"+cell.id+"的值为:"+newData);
			if(oThis.col.mode=="number"||oThis.col.mode=="percent"){
				newData = new Number(newData);
				if(newData==NaN) newData=0;
			}
			rowData.s$(oThis.name,newData);
			if(evtTrigger===true){
				var event = new Object();
				event.cell = oThis;
				event.oldValue = oldData;
				event.newValue = newData;
				oThis.row.grid.onCellValueChanged(event);
			}
			if(row.grid.aggRow!=null)
				row.grid.aggRow.refreshAggValue(oThis.col);
		}
		oThis.repaint();
	}
	this.getValue = function(){
		return oThis.row.getCellValue(oThis.col);
	}
}
function SigmaAggRow(grid){
	this.buf = null;
	var aggCols = grid.context.aggregate;
	var oThis = this;
	this.refreshAggValue = function(col){
		oThis.buf=null;
		var acol = null;
		for(var i=0;i<aggCols.length;i++){
			var acol = aggCols[i];
			if(acol.col==col.name){
				var data = grid.getValue();
				var exp = "obj = grid."+acol.exp+"('"+acol.col+"',data)";
				acol._value = eval(exp);
				break;
			}else acol=null;
		}
		if(acol==null) return;
		var index = 0;
		if(grid.context.sequence==true) index++;
		if(grid.context.radioBox==true) index++;
		else if(grid.context.checkBox==true) index++;
		var cindex = index + col.colIndex;
		var cell =null;
		var rows = oThis.getElements();
		
		if(cindex<index+grid.context.locked){
			cell = rows[0].cells[cindex];
		}else{
			cell = rows[1].cells[col.colIndex-grid.context.locked];
		}
		var data = new Number(acol._value);
		
		if(acol.format!=null) data = data.format(acol.format);
		else if(col.format!=null) data = data.format(col.format);
		cell.innerHTML = data;
	}
	this.getElements = function(){
		var tbl = grid.getLeftTb();
		var tbr = grid.getRightTb();
		var rowL = tbl.rows[tbl.rows.length-1];
		var rowR = tbr.rows[tbr.rows.length-1];
		var elements = [];
		elements.push(rowL);
		elements.push(rowR);
		return elements;
	}
	
	this.calcAggRowValue = function(){
		for(var i=0;i<aggCols.length;i++)aggCols[i]._value = 0;
		var rows = grid.rows;
		if(rows==null || rows.length==0)return;
		var data = grid.getValue();
		for(var i=0;i<aggCols.length;i++){
			var c = aggCols[i];
			var exp = "obj = grid."+c.exp+"('"+c.col+"',data)";
			c._value = eval(exp);
		}
	}
	oThis.calcAggRowValue();
	this.getAggColByName = function(name){
		for(var i=0;i<aggCols.length;i++){
			if(aggCols[i].col==name) return aggCols[i];
		}
		return null;
	}
	this.paint2Str = function(){
		var leftCount = 0;
		if(grid.context.checkBox==true)	leftCount++;
		else if(grid.context.radioBox==true) leftCount ++;
		if(grid.context.sequence==true) leftCount ++;
		var sb = [];
		var sbr = [];
		sb.push("<tr >");
		sb.push("<td align=center colspan="+leftCount+">合计</td>");
		var columns =grid.leafCols;
		for(var i=0;i<columns.length;i++){
			var col = columns[i];
			var align = "right";
			if(col.align!=null) align = col.align;
			var acol = oThis.getAggColByName(col.name);
			var buf = [];
			if(acol==null){
				buf.push('<td align='+align);
				buf.push('>&nbsp;</td>');
			}else{
				var data = new Number(acol._value);
				if(acol.format!=null) data = data.format(acol.format);
				else if(col.format!=null) data = data.format(col.format);
				buf.push('<td align='+align+'>');
				buf.push(data);
				buf.push('</td>');
			}
			if(i<grid.context.locked){
				sb.push(buf.join(""));
				if(i===grid.context.locked-1)
					sb.push("</tr>");
			}else{
				if(sbr.length==0) sbr.push("<tr >");
				sbr.push(buf.join(""));
			}
		}
		sbr.push("</tr>");
		var r = [];
		r.push(sb.join(""));r.push(sbr.join(""));
		return r;
	}
}
function SigmaRow(grid,rowData,index){
	this.grid = grid;
	this.rowData = rowData;
	this.readonly = false;
	this._rId = grid.getNextRowId();
	this._index = index;
	this._selected = false;
	this.buf = null;
	var oThis = this;
	this.paintCell = function(col){
		var str = grid.getColumnRender(col).paint(grid,oThis,col);
		var sb = new Array();
		var cellId = "cell@"+oThis._rId+"@"+col.name;
		var align = "center";
		if(col.align!=null)	align = col.align;
		else align = defaultAlign[col.mode];
		sb.push('<td id='+cellId);
		sb.push(' onclick=s_grid_cellOnClick('+grid.id+',this,event)');
		sb.push(' ><div style="text-align:'+align+';"');
		sb.push('>'+str);
		sb.push('</div></td>');
		return sb.join("");
	}
	this.paintCell2Td = function(col,td){
		var str = grid.getColumnRender(col).paint(grid,oThis,col);
		var sb = new Array();
		td.id = "cell@"+oThis._rId+"@"+col.name;
		var align = "center";
		if(col.align!=null)	align = col.align;
		else align = defaultAlign[col.mode];
		if(SigmaUtil.isIE()){
			td.attachEvent("onclick",
				function(e){s_grid_cellOnClick(grid.id,td,e)}
			);
		}else{
			td.addEventListener("click",
				function(e){s_grid_cellOnClick(grid.id,td,e)},
				false
			);
		}
		sb.push('<div style="text-align:'+align+';"');
		sb.push('>'+str);
		sb.push('</div>');
		td.innerHTML = sb.join("");
	}
	this.paint2Table = function(){
		var doms = oThis.getElements();
		if(doms==null){
			var leftTb = grid.getLeftTb();
			var rightTb = grid.getRightTb();
			var lr = leftTb.insertRow(oThis._index);
			lr.id = oThis._rId;
			var rr = rightTb.insertRow(oThis._index);
			rr.id = oThis._rId;
			var cindex = 0;
			var cell = null;
			var sb = [];
			if(grid.context.radioBox==true){
				cell = lr.insertCell(cindex);cindex++;
				cell.align = "center";
				sb.push('<input type="radio" name="auto_radio_'+grid.id+'"');
				sb.push(' onclick="s_grid_onRowRadioCheck(');
				sb.push(grid.id + ',');
				sb.push(oThis._rId + ',this.checked)"/>');
				cell.innerHTML = sb.join("");
			}else if(grid.context.checkBox ==true){
				cell = lr.insertCell(cindex);cindex++;
				cell.align = "center";
				sb.push('<input type="checkbox" name="auto_check_'+grid.id+'"');
				sb.push(' onclick="s_grid_onRowCheck(');
				sb.push(grid.id + ',');
				sb.push(oThis._rId + ',this.checked)">');
				cell.innerHTML = sb.join("");
			}
			if(grid.context.sequence==true){
				cell = lr.insertCell(cindex);cindex++;
				cell.innerHTML = oThis._index+1;
				cell.align = "center";
			}
			var columns =grid.leafCols;
			for(var i=0;i<columns.length;i++){
				var td = null;
				if(i<grid.context.locked){
					td = lr.insertCell(cindex);cindex++;
				}else{
					if(i==grid.context.locked) cindex=0;
					td = rr.insertCell(cindex);cindex++;
				}
				oThis.paintCell2Td(columns[i],td);
			}
		}else{
			//重绘该行数据
		}
	}
	this.paint2Str = function(){
		if(oThis.buf!=null) return oThis.buf;
		var sb = [];
		var sbr = [];
		sb.push("<tr id="+oThis._rId+" class='"+(oThis._selected==true?"selected":"")+"' onmouseover=''>");
		sbr.push("<tr id="+oThis._rId+" class='"+(oThis._selected==true?"selected":"")+"' onmouseover=''>");
		if(grid.context.checkBox==true){
			sb.push('<td align="center">');
			sb.push('<input type="checkbox" name="auto_check_'+grid.id+'"');
			sb.push(oThis._selected===true?' checked':'');
			sb.push(' onclick="s_grid_onRowCheck(');
			sb.push(grid.id + ',');
			sb.push(oThis._rId + ',this.checked)"></td>');
		}else if(grid.context.radioBox==true){
			sb.push('<td align="center">');
			sb.push('<input type="radio" name="auto_radio_'+grid.id+'"');
			sb.push(oThis._selected===true?' checked':'');
			sb.push(' onclick="s_grid_onRowRadioCheck(');
			sb.push(grid.id + ',');
			sb.push(oThis._rId + ',this.checked)"/></td>');
		}
		if(grid.context.sequence==true){
			sb.push('<td align="center">');
			sb.push((oThis._index+1) + '</td>');
		}
		var columns =grid.leafCols;
		for(var i=0;i<columns.length;i++){
			if(i<grid.context.locked){
				sb.push(oThis.paintCell(columns[i]));
				if(i===grid.context.locked-1) sb.push("</tr>");
			}else sbr.push(oThis.paintCell(columns[i]));
		}
		sbr.push("</tr>");
		var r =[];
		r.push(sb);r.push(sbr);
		oThis.buf = r;
		return r;
	}
	this.setData = function(data){
		oThis.buf = null;
		oThis.rowData = data;
		oThis.repaint();
	}
	this.cells = function(){
		var cells = {};
		var cols = oThis.grid.leafCols;
		for(var i=0;i<cols.length;i++){
			var cell = new SigmaCell(oThis,cols[i]);
			cells[cols[i].name] = cell;
		}
		return cells;
	}
	this.getCellValue = function(col){
		var rowData = oThis.rowData;
		if(col.formula==null){
			return rowData.p$(col.name);
		}else{
			var formula = col.formula.replace(/p\$/ig,"rowData.p$");
			return eval("obj="+formula);
		}
	}
	
	this.getElements = function(){
		return grid.getRowDoms(oThis._rId);
	}
	this.removeElements = function(){
		var doms = oThis.getElements(oThis._rId);
		doms[0].parentNode.removeChild(doms[0]);
		doms[1].parentNode.removeChild(doms[1]);
	}
	this.setSelected = function(checked){
		oThis._selected = checked;
		oThis.buf = null;
		var doms = oThis.getElements();
		if(doms==null) return ;
		var input = null;
		if(grid.context.checkBox==true){
			input =doms[0].cells[0].childNodes[0];
			input.checked=checked;
			if(checked==false)
				grid.getHeadCheckBox().checked = checked;
		}else if(grid.context.radioBox==true){
			input =doms[0].cells[0].childNodes[0];
			input.checked=checked;
			if(checked==true){
				var rows = oThis.grid.getSelectedRows();
				for(var i=0;i<rows.length;i++){
					if(rows[i]!=oThis)
						rows[i].setSelected(false);
				}
			}
		}
		if(checked==true){
			doms[0].className = "selected";
			doms[1].className = "selected";
		}else{
			doms[0].className = "";
			doms[1].className = "";
		}
	}
}

var sgrid_StringRender = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		if(data===null ||  data===undefined){
			return "";
		}
		return data;
	}
}
	
var sgrid_NumberRender = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		var n = new Number(data);
		var r ;
		if(!isFinite(n)) n = new Number(0);
		if(col.format!=null) r = n.format(col.format);
		return r;
	}
}
var sgrid_BoolRender = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		var c = (data===true)?'是':'否';
		return c;
	}
}
var sgrid_LinkRender = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		var t=[];
		t[0] = '<a href="#" onClick="javascript:' + col.href + '(' 
		t[1] = + row._rId 
		t[2] = ',\''+ data + '\');">' 
		t[3] =  data + '</a>'
		return t.join('');
	}
}
var sgrid_SelectRender = new function(){
	this.paint = function(grid,row,col){
		var id = row.getCellValue(col);
		var options = col.options;
		var value = null;
		for(var i=0;i<options.length;i++){
			if(options[i].id === id) {value=options[i];break;}
		}
		if(value!=null) return value.name;
		else return "&nbsp;";
	}
	
}

var sgrid_SelectEditor = new function(){
	this.paint = function(grid,row,col){
		var data =  row.getCellValue(col);
		var s = [];
		s[s.length] = '<select onblur="s_grid_cellBlur('
		s[s.length]= grid.id+',this.parentNode,event);"'
		s[s.length] ='" onkeydown="s_grid_cellFocusHandle('
		s[s.length] = grid.id
		s[s.length] =',this.parentNode,event);" style="border-width:0px;height:17px;width:100%;">'
		for(var i=0;i<col.options.length;i++){
			s[s.length] = '<option value='
			s[s.length] = col.options[i].id
			if(data==col.options[i].id)
				s[s.length] = ' selected'
			s[s.length] = '>'+col.options[i].name
			s[s.length] = '</option>'
		}
		s[s.length] = '</select>'
		return s.join("");
	}
}
var sgrid_BoolEditor = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		var s = [];
		s[s.length] = '<input type=checkbox onblur="s_grid_cellBlur('
		s[s.length]= grid.id+',this.parentNode,event);"'
		s[s.length] ='" onkeydown="s_grid_cellFocusHandle('
		s[s.length] = grid.id;
		s[s.length] =',this.parentNode,event);" style=""';
		s[s.length] = (data===true)?' checked':' ';
		s[s.length] = ' />';
		return s.join('');
	}
}

var sgrid_StringEditor = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		if(data===null || data===undefined) data = "";
		var s = [];
		s[s.length] = '<input type=text onblur="s_grid_cellBlur('
		s[s.length]= grid.id+',this.parentNode,event);"'
		s[s.length] ='" onkeydown="s_grid_cellFocusHandle('
		s[s.length] = grid.id;
		s[s.length] =',this.parentNode,event);" style="border-width:0px;height:19px;width:100%;background:#dbeafb;border-bottom:1px solid #c1cedf;line-height:19px;padding-left:2px;" maxsize=255';
		s[s.length] =' value="'+data+'"/>';
		return s.join('');
	}
}

var sgrid_NumberEditor = new function(){
	this.paint = function(grid,row,col){
		var data = row.getCellValue(col);
		var n = new Number(data);
		if(!isFinite(n)) data = new Number(0);
		var s = [];
		s[s.length] = '<input type=text onblur="s_grid_cellBlur('
		s[s.length]= grid.id+',this.parentNode,event);"'
		s[s.length] ='" onkeydown="s_grid_cellFocusHandle('
		s[s.length] = grid.id;
		s[s.length] =',this.parentNode,event);" style="border-width:0px;height:19px;background:#dbeafb;line-height:19px;width:100%;" maxsize=255';
		s[s.length] =' value="'+data+'"/>';
		return s.join('');
	}
}

function SigmaGrid(parentNode,context,columns){
	this.sum = function(colName,data){
		var s = 0;
		for(var i=0;i<data.length;i++){
			var v = data[i].p$(colName);
			if(v==null) v = 0;
			s = s+v;
		}
		return s;
	}
	this.count = function(colName,data){
		var c = 0;
		for(var i=0;i<data.length;i++){
			var v = data[i].p$(colName);
			if(v!=null) c++;
		}
		return c;
	}
	this.avg = function(colName,data){
		var s = oThis.sum(colName,data);
		return s/data.length;
	}
	this.min = function(colName,data){
		var r = data[0].p$(colName);
		if(r==null) r = 0;
		for(var i=1;i<data.length;i++){
			var v = data[i].p$(colName);
			if(v==null) v = 0;
			if(v<r) r = v;
		}
		return r;
	}
	this.max = function(colName,data){
		var r = data[0].p$(colName);
		if(r==null) r=0;
		for(var i=1;i<data.length;i++){
			var v = data[i].p$(colName);
			if(v==null) v = 0;
			if(v>r) r = v;
		}
		return r;
	}
	var u = SigmaUtil;
	this.cols = columns;			//列定义
	this.rows = [];					//当前显示的行对象
	this.scrollTop = 0;
	this.scrollLeft = 0;
	this.context = context;
	if(context.locked === undefined) context.locked = 0;
	
	if(typeof(parentNode)=="string" ){
		this.parent = u.$(parentNode);
	}else{
		this.parent = parentNode;
	}
	this.element = document.createElement("div");
	this.parent.appendChild(this.element);
	this.element.style.height = this.parent.clientHeight;
	this.element.style.width = this.parent.clientWidth;
	
	u.register(this);
	this.element.id = this.id;
	var oThis = this;
	this.headWide = null;	//列总数，重新绑定表头时需要把这个值重置为null;
	this.headDeep = null;	//表头嵌套深度，重新绑定表头时需要把这个值重置为null;
	this.headHeight = null;	//表头高度
	this.bodyHeight = null;	//数据区高度
	this.colsWidth = null;	//所有列宽度之和
	this.cellHeight = 20;	//单个单元格的高度
	if(window._sgrid_renders!=null){
		this.Renders = window._sgrid_renders;
		this.Editors = window._sgrid_editors
	}else{
		this.Renders = new Object();
		this.Renders.registered = new Object();
		window._sgrid_renders = this.Renders;
		this.Editors = new Object();
		this.Editors.registered = new Object();
		window._sgrid_editors = this.Editors;
	}
	this.Renders.getRender = function(mode){
		return oThis.Renders.registered[mode];
	}
	this.Renders.register = function(mode,render){
		return oThis.Renders.registered[mode] = render;
	}
	this.Editors.register = function(mode,editor){
		return oThis.Editors.registered[mode] = editor;
	}
	this.Editors.getEditor = function(mode){
		return oThis.Editors.registered[mode];
	}
	//注册缺省的绘制器
	this.Renders.register("string",sgrid_StringRender);
	this.Renders.register("boolean",sgrid_BoolRender);
	this.Renders.register("number",sgrid_NumberRender);
	this.Renders.register("link",sgrid_LinkRender);
	this.Renders.register("select",sgrid_SelectRender);
	
	this.Editors.register("string",sgrid_StringEditor);
	this.Editors.register("boolean",sgrid_BoolEditor);
	this.Editors.register("number",sgrid_NumberEditor);
	this.Editors.register("select",sgrid_SelectEditor);
	
	var sb = [];
	sb[sb.length] = '<div id="head_'+ this.id+ '" style="overflow:hidden;width:200px;height:20px;">';
	sb[sb.length] = '<div class="head" id="lHead_' + this.id + '" style="overflow:hidden;float:left;width:200px;height:20px;">';
	sb[sb.length] = 'left head</div>';
	sb[sb.length] = '<div class="head" id="rHead_' + this.id + '" style="overflow:hidden;float:left;width:280px;height:20px;">';
	sb[sb.length] = 'right head</div>';
	sb[sb.length] = '</div>';
	sb[sb.length] = '<div id="body_'+this.id+'" style="overflow:hidden;z-index:2;width:200px;height:200px;">';
	sb[sb.length] = '<div class="body" id="lBody_' + this.id + '" style="height:200px;width:200px;float:left;overflow:hidden;position:relative;"> ';
	sb[sb.length] = 'left body</div>';
	sb[sb.length] = '<div class="body" id="rBody_' + this.id + '" style="height:200px;width:280px;float:left;overflow:hidden;position:relative;"> ';
	sb[sb.length] = 'right body</div>';
	sb[sb.length] = '</div>';
	sb[sb.length] = '<div class="scroll" id="scroll_' + this.id + '" onscroll="s_grid_onScroll('+oThis.id+',this.scrollLeft,this.scrollTop);"  style="z-index:-1;top:-200px;overflow:scroll;position:relative;width:280px;height:200px;"> ';
	sb[sb.length] = '<div id="sPane_' + this.id + '" style="height:500px;width:200px;"> ';
	sb[sb.length] = '</div>';
	sb[sb.length] = '</div>';
	sb[sb.length] = '<div  id="status" style="background-color:rgb(240,240,240);padding-top:1px;padding-left:2px;font-size:12px;height:20px;width:0px;float:left;overflow:hidden;position:relative;"> ';
	sb[sb.length] = '</div>';
	sb[sb.length] = '<div  id="pageCtl" class="SigmaPage" style="display:none;"> ';
	sb[sb.length] = '分页:</div>';
	this.element.className = "SigmaGrid";
	this.element.innerHTML = sb.join("");
	oThis.id = this.element.id;
	this.getHeadBox = function(){return u.$("head_"+this.id)}
	this.getLeftHead = function(){return u.$("lHead_"+this.id)}
	this.getRightHead = function(){return u.$("rHead_"+this.id)}
	this.getBodyBox = function(){return u.$("body_"+this.id)}
	this.getPageCtl = function(){
		if(oThis.context.pageCtl!=null) {
			if(oThis._pageCtl==null){
			 	var div = u.$$(this.element,"pageCtl");
			 	div.style.display= "";
			 	oThis._pageCtl = new SigmaPage(div,oThis.context.pageCtl,oThis);
			}
			return oThis._pageCtl;
		}
		return null;
	}
	this.getScrollBox = function(){return u.$("scroll_"+this.id)}
	this.getLeftBody = function(){return u.$("lBody_"+this.id)}
	this.getRightBody = function(){return u.$("rBody_"+this.id)}
	this.getStatusBox = function(){return u.$$(this.element,"status")}
	this.getScrollPane = function(){return u.$("sPane_"+this.id)}
	
	this.getNextRowId = function(){
		oThis._rIndex = oThis._rIndex+1;
		return oThis._rIndex;
	}
	//计算表头层次深度
	this.countHeadDeep = function(col){
		if(oThis.headDeep!==null)
			return oThis.headDeep;
		var deep ;
		var children ;
		if(col===undefined){
			oThis.leafCols = [];
			deep = 0;
			children = oThis.cols;
		}else{
			deep = 1;
			children = col.children;
		}
		var maxCDeep = 0;
		if(children!==undefined && children.length>0){
			for(var i=0;i<children.length;i++){
				var c = children[i];
				var cdeep = oThis.countHeadDeep(c);
				if(cdeep>maxCDeep){
					maxCDeep = cdeep;
				}
			}
		}
		if(col!==undefined){
			col._cdeep = maxCDeep;
		}else{
			oThis.headDeep = maxCDeep;
			oThis.headHeight = maxCDeep * oThis.cellHeight;
		}
		return deep + maxCDeep;
	}
	//计算列的广度，包括每列包含子列的广度
	this.countHeadWide = function(col){
		if(oThis.headWide!==null)
			return oThis.headWide;
		var acw ;
		var children ;
		if(col===undefined){
			acw = 0;
			children = oThis.cols;
		}else{
			acw = 1;
			children = col.children;
		}
		if(children!==undefined && children.length>0){
			acw = 0;
			for(var i=0;i<children.length;i++){
				var c = children[i];
				var cw = oThis.countHeadWide(c);
				acw = acw +cw;
			}
		}else{
			col.colIndex = oThis.leafCols.length;
			oThis.leafCols[oThis.leafCols.length ] = col;
		}
		if(col!==undefined){
			col._colspan = acw;
			return acw;
		}else{
			oThis.headWide = acw;
			return oThis.headWide;
		}
	}
	this.calcRowSpan = function(cols,deep){
		if(cols===undefined){
			cols = oThis.cols;
			deep = oThis.countHeadDeep();
		}
		for(var i=0;i<cols.length;i++){
			var col = cols[i];
			col._rowspan = deep-col._cdeep;
			var cs = col.children;
			if(cs!==undefined && cs.length>0){
				oThis.calcRowSpan(cs,deep-1);
			}
		}
	}
	this.getColWidth = function(col){
    if(!(col.width)) return 100;
    
    if(typeof col.width == "string") {
    	var sumWidth = oThis.element.clientWidth - 19;
			if(oThis.context.sequence==true) sumWidth = sumWidth-40;
			if(oThis.context.checkBox ==true) sumWidth = sumWidth-40;
		  else if(oThis.context.radioBox==true)sumWidth = sumWidth+40;
    	
    	var colWidth = (sumWidth*parseFloat(col.width)/100);
    	if(colWidth<10) colWidth = 10;
    	return colWidth;
    }
    
    if(typeof col.width == "number") return col.width;
    
    return 100;
	}
	this.countLeftWidth = function(){
		var width = 0;
		for(var i=0;i<oThis.context.locked;i++){
			width = width+ oThis.getColWidth(oThis.leafCols[i]);
		}
		if(oThis.context.sequence==true) width = width+40;
		if(oThis.context.checkBox ==true) width = width+40;
		else if(oThis.context.radioBox==true)width = width+40;
		return width;
	}
	this.countRightWidth = function(){
		var width = 0;
		for(var i=oThis.context.locked;i<oThis.leafCols.length;i++){
			width = width +oThis.getColWidth(oThis.leafCols[i]);
		}
		return width;
	}
	this.setColWidth = function(col,newWidth){
		var rHead = oThis.getRightHead();
		var colgroups = u.$$(rHead,"colgroup_"+oThis.id);
		var c = u.$$(colgroups,"col_"+col.name);
		var titleDiv = u.$$(rHead,"title_"+col.name);
		titleDiv.style.width = newWidth - 6;
		col.width = newWidth;
		c.width = newWidth;
		oThis.rightColGroup = null;
	}
	
	this.resetLayout = function(){
		var headDeep = oThis.countHeadDeep();
		var headWide = oThis.countHeadWide();
		if(oThis.context.locked === oThis.leafCols.length)oThis.context.locked = 0;
		var headHeight = oThis.cellHeight*headDeep;
		if(u.isIE()==false) headHeight+=headDeep;
		var leftWidth = oThis.countLeftWidth();
		var rightWidth = oThis.countRightWidth();
		var headBox = oThis.getHeadBox();
		var leftHead = oThis.getLeftHead();
		var rightHead = oThis.getRightHead();
		var rightBody = oThis.getRightBody();
		var leftBody = oThis.getLeftBody();
		var bodyBox = oThis.getBodyBox();
		headBox.style.height = headHeight;
		headBox.style.width = oThis.element.clientWidth;
		bodyBox.style.width = oThis.element.clientWidth-17;
		var pageCtl = oThis.getPageCtl();
		
		if(pageCtl==null)
			bodyBox.style.height = oThis.element.clientHeight-headHeight-17;
		else
			bodyBox.style.height = oThis.element.clientHeight-headHeight-17-30;
		leftHead.style.height = headHeight;
		leftHead.style.width = leftWidth;
		rightHead.style.height = headHeight;
		rightHead.style.width = oThis.element.clientWidth - leftWidth;
		leftBody.style.width = leftWidth;
		leftBody.style.height = bodyBox.clientHeight;
		rightBody.style.width =  2000;
		rightBody.style.height = bodyBox.clientHeight;
		rightBody.style.top = -leftBody.clientHeight;
		rightBody.style.left = leftBody.clientWidth;
		
		var scrollBox = oThis.getScrollBox();
		scrollBox.style.width = headBox.clientWidth;//-leftWidth;
		scrollBox.style.top = - bodyBox.clientHeight;
		scrollBox.style.height = bodyBox.clientHeight+17;
		scrollBox.style.left = 0;//leftWidth;
		var scrollPane = oThis.getScrollPane();
		scrollPane.style.width = rightWidth + leftWidth;
		
		var statusbox = oThis.getStatusBox();
		statusbox.style.top = - bodyBox.clientHeight-16;
		statusbox.style.height = 16;
		statusbox.style.width = 0;//leftWidth-2;
		statusbox.style.overflow = "hidden";
		statusbox.style.whiteSpace = "nowrap";
		statusbox.style.display='inline';
		if(pageCtl!=null){
			if(u.isIE())
				pageCtl.element.style.top = - bodyBox.clientHeight-8;
			else
				pageCtl.element.style.top = - bodyBox.clientHeight+6;
			pageCtl.element.style.width = oThis.element.clientWidth;
		}

		for(var ris=0; ris<oThis.cols.length; ris++){

			var col = oThis.cols[ris];
			
			var oldWidth = col.width
	    if(typeof col.width == "string") {
	    	var sumWidth = oThis.element.clientWidth - 19;
				if(oThis.context.sequence==true) sumWidth = sumWidth-40;
				if(oThis.context.checkBox ==true) sumWidth = sumWidth-40;
			  else if(oThis.context.radioBox==true)sumWidth = sumWidth+40;
	    	
	    	var colWidth = (sumWidth*parseFloat(col.width)/100);
	    	if(colWidth<10) colWidth = 10;
	    	try{oThis.setColWidth(col, colWidth);oThis.endResize(col)}catch(e){}
	    	col.width = oldWidth;
	    }
			
		}
	}
	
	//将grid自适应外面容器的大小. 修改:郭浩 2007/10/18
	function parentResize(){
		this.innerGrid.element.style.height = this.style.height;
		this.innerGrid.element.style.width = this.style.width;
		this.innerGrid.resetLayout();
		//alert("Resize");
	}
	function parentPropertychange(){
		if(window.event.propertyName === "style.height" ||  window.event.propertyName === "style.width"){
			this.innerGrid.element.style.height = this.style.height;
			this.innerGrid.element.style.width = this.style.width;
			this.innerGrid.resetLayout();
		}
		alert(window.event.propertyName);
	}
	this.parent.innerGrid = oThis;
	this.parent.onresize = parentResize;
	//this.parent.onpropertychange = parentPropertychange;

	this.status = function(s){
		if(s!==undefined)
			oThis.getStatusBox().innerHTML = s;
		else 
			return oThis.getStatusBox().innerHTML;
		
	}
	
	this.getLeftColGroup = function(){
		if(oThis.leftColGroup!=null) return oThis.leftColGroup;
		var sb = [];
		sb.push("<COLGROUP id='colgroup_"+oThis.id+"'>");
		if(oThis.context.checkBox==true) sb.push('<COL width='+40+'/>');
		else if(oThis.context.radioBox ==true) sb.push('<COL width='+40+'/>');
		if(oThis.context.sequence == true) sb.push('<COL width='+40+'/>');
		for(var i=0;i<oThis.context.locked;i++){
			var col = oThis.leafCols[i];
			sb.push('<COL width=')
			sb.push(oThis.getColWidth(col));
			sb.push(' id="col_'+col.name);
			sb.push('"/>');
		}
		sb.push("</COLGROUP>");
		oThis.leftColGroup = sb;
		return sb;
	}
	this.getRightColGroup = function(){
		if(oThis.rightColGroup!=null) return oThis.rightColGroup;
		var sb = [];
		sb.push("<COLGROUP id='colgroup_"+oThis.id+"'>");
		for(var i=oThis.context.locked;i<oThis.leafCols.length;i++){
			var col = oThis.leafCols[i];
			sb.push('<COL width=');
			sb.push(oThis.getColWidth(col));
			sb.push(' id="col_'+col.name);
			sb.push('"/>');
		}
		sb.push("</COLGROUP>");
		oThis.rightColGroup = sb;
		return sb;
	}
	this.getColGroup = function(){
		var sb = [];
		var left = oThis.getLeftColGroup();
		var right = oThis.getRightColGroup();
		sb.push("<COLGROUP id='colgroup_"+oThis.id+"'>");
		for(var i=1;i<left.length-1;i++){sb.push(left[i]);}
		for(var i=1;i<right.length-1;i++){sb.push(right[i]);}
		sb.push("</COLGROUP>");
		return sb;
	}
	this.paintHeadLeft = function(colsbuf){
		var cellbuf = [];
		var deep = oThis.countHeadDeep();
		if(oThis.context.checkBox===true){
			cellbuf[cellbuf.length] = '<TD align=middle valign=middle';
			cellbuf[cellbuf.length] = ' rowspan='+deep;
			cellbuf[cellbuf.length] = '><input type="checkbox" id="headCheck_'+oThis.id+'" onclick="s_grid_headCheckAll('+oThis.id+',this.checked)"/></TD>';
			oThis.autoColCount = oThis.autoColCount+1;
		}else if(oThis.context.radioBox ===true){
			cellbuf[cellbuf.length] = '<TD align=middle valign=middle';
			cellbuf[cellbuf.length] = ' rowspan='+deep;
			cellbuf[cellbuf.length] = '>&nbsp</TD>';
			oThis.autoColCount = oThis.autoColCount+1;
		}
		if(oThis.context.sequence === true){
			cellbuf[cellbuf.length] = '<TD align=middle valign=middle';
			cellbuf[cellbuf.length] = ' rowspan='+deep;
			cellbuf[cellbuf.length] = '>序号</TD>';
			oThis.autoColCount = oThis.autoColCount+1;
		}
		return cellbuf.join("");
	}

	this.paintHeadCell = function(col,rowsbuf){
		var width = oThis.getColWidth(col);
		var title = [];
		if(col.colIndex<oThis.context.locked || (col.children!=null&&col.children.length>0)){
			title[0] = '<div id="title_'+ col.name+'" class="title" style="cursor:pointer;width:100%;" onclick="s_grid_sortCol('+oThis.id+',\''+col.name+'\');">'+col.caption+'</div>';
			title = title.join("");
		}else{
			title[0] = '<div id="title_'+ col.name+'" class="title" style="float:left;cursor:pointer;width:'+(width-6)+'px;" onclick="s_grid_sortCol('+oThis.id+',\''+col.name+'\');">'+col.caption+'</div>';
			title[1] = '<div id="resize_'+ col.name+'" style="float:right;cursor:e-resize;width:5px;height:90%;" onmousedown="s_grid_resize('+oThis.id+',\''+col.name+'\',event);"></div>';
			title = title.join("");
		}
		var rowbuf = rowsbuf[col._selfDeep];
		var cellbuf = [];
		cellbuf.push('<TD align=middle valign=middle');
		cellbuf.push(' colspan='+col._colspan);
		cellbuf.push(' rowspan='+col._rowspan);
		cellbuf.push('>'+title);
		cellbuf.push('</TD>');
		rowbuf[rowbuf.length] = cellbuf.join("");
		if(col.children!== undefined && col.children.length>0){
			var children = col.children;
			for(var i=0;i<children.length;i++){
				var child = children[i];
				child._selfDeep = col._selfDeep +1;
				oThis.paintHeadCell(child,rowsbuf);
			}
		}
	}
	
	this.paintHeader = function(){
		oThis.calcRowSpan();
		var sb = [];
		sb.push('<div style="width:2000px;"><TABLE id=tLeftHead_'+oThis.id+' style="TABLE-LAYOUT:fixed;position:relative;" cellSpacing=0 cellPadding=0 border=0>');
		var rowsbuf = []; 
		var deep = oThis.countHeadDeep();
		for(var i=0;i<deep;i++){
			var rowbuf = [];
			rowsbuf.push(rowbuf);
			rowbuf.push('<TR>');
		}
		rowsbuf[0].push(oThis.paintHeadLeft());
		for(var i=0;i<oThis.cols.length;i++){
			var col = oThis.cols[i];
			col._selfDeep = 0;
			oThis.paintHeadCell(col,rowsbuf);
		}
		for(var i=0;i<deep;i++){
			var rowbuf = rowsbuf[i];
			rowbuf.push('</TR>');
			rowsbuf[i]=rowbuf.join("");
		}
		sb.push(rowsbuf.join(""));
		sb.push(oThis.getColGroup().join(""));
		sb.push('</TABLE></div>');
		var ts = sb.join("");
		//绘制左边表头
		var leftHead  = oThis.getLeftHead();
		leftHead.innerHTML = ts;
		//绘制右边表头
		var rightHead = oThis.getRightHead();
		rightHead.innerHTML =ts;
		var rightHeadTb = u.$$(rightHead,"tLeftHead_"+oThis.id);
		rightHeadTb.style.left = -oThis.countLeftWidth();
	}
	
	this.getVisRowsAmount = function(){
		if(oThis.visRowsAmount==null){
			var h = oThis.getVisHeight();
			var a = h / oThis.cellHeight;
			a= Math.round(a);
			if(oThis.context.aggregate!=null && oThis.context.aggregate.length>0){
				oThis.visRowsAmount = a-1;
			}else oThis.visRowsAmount=a;
		}
		return oThis.visRowsAmount;
	}
	this.getVisHeight = function(){
		return oThis.getBodyBox().clientHeight;
	}
	this.getColumnEditor = function(col){
		if(col.editor==null){
			if(col.mode==null) col.mode = "string";
			var r = oThis.Editors.getEditor(col.mode)
			col.editor = r;
		}
		return col.editor;
	}
	this.getColumnRender = function(col){
		if(col.render==null){
			if(col.mode==null)	col.mode = "string";
			var r = oThis.Renders.getRender(col.mode);
			col.render = r;
		}
		return col.render;
	}
	this.paintRows = function(from){
		oThis.from = from;
		var mode = oThis.getPaintMode();
		var end = 0;
		var rows = oThis.rows;
		if(mode=="all"){
			from = 0; end = rows.length;
		}else{
			var visRowsAmount =oThis.getVisRowsAmount();
			end = from +visRowsAmount;
			if(end>rows.length) end = rows.length;
		}
		var sb = new Array();
		var sbr = new Array();
		sb.push('<table id="dataTable" cellspacing=0 cellpadding=0 border=0 style="table-layout:fixed;position:relative;">');
		sb.push(oThis.getLeftColGroup().join(""));
		sbr.push('<table id="dataTable" cellspacing=0 cellpadding=0 border=0 style="table-layout:fixed;position:relative;float:left;">');
		sbr.push(oThis.getRightColGroup().join(""));
		
		for(var i=from;i<end;i++){
			var sbs = rows[i].paint2Str();
			sb.push(sbs[0].join(""));
			sbr.push(sbs[1].join(""));
		}
		if(oThis.aggRow!=null){
			var aggStrs = oThis.aggRow.paint2Str();
			sb.push(aggStrs[0]); 
			sb.push('</table>');
			sbr.push(aggStrs[1]);
			sbr.push('</table>');
		}
		var leftBody = oThis.getLeftBody();
		var rightBody = oThis.getRightBody();
		leftBody.innerHTML = sb.join('');
		rightBody.innerHTML = sbr.join('');
		var rightTb = u.$$(rightBody,"dataTable");
		rightTb.style.left=-oThis.getScrollBox().scrollLeft;
		//oThis.status("绘制表格完成！");
	}
	this.getLeftTb = function(){
		var lb = oThis.getLeftBody();
		return u.$$(lb,"dataTable");
	}
	this.getRightTb = function(){
		var rb = oThis.getRightBody();
		return u.$$(rb,"dataTable");
	}
	this.resetScroll = function(){
		var spane= oThis.getScrollPane();
		var lbody = oThis.getLeftBody();
		var ltb = u.$$(lbody,"dataTable");
		if(oThis.context.aggregate!=null && oThis.context.aggregate.length>0)
			spane.style.height = (oThis.rows.length+1) * oThis.cellHeight;
		else
			spane.style.height = oThis.rows.length * oThis.cellHeight;
	}
	this.getPaintMode = function(){
		if(oThis.context.paintMode=="all"){
			return "all";
		}else if(oThis.context.paintMode=="view"){
			return "view";
		}else if(oThis.context.paintMode =="auto"){
			if(oThis.rows.length>oThis.context.paintValve){
				return 'view';
			}else 
				return "all";
		}
	}
	this.getSelectedRows = function(){
		var rows = oThis.rows;
		var selected = [];
		for(var i=0;i<rows.length;i++){
			if(rows[i]._selected===true) selected.push(rows[i]);
		}
		return selected;
	}
	this.getHeadCheckBox = function(){
		var headPane = oThis.getLeftHead();
		return u.$$(headPane,"headCheck_"+oThis.id);
	}
	this.getRowDom = function(tb,rowId){
		for(var i=0;i<tb.rows.length;i++){
			var row = tb.rows[i];
			if(row.id == rowId) return row;
		}
		return null;
	}
	this.getRowDoms = function(rowId){
		var doms = [];
		var tbr = oThis.getRightTb();
		var tbl = oThis.getLeftTb();
		var trl = oThis.getRowDom(tbl,rowId);
		var trr = oThis.getRowDom(tbr,rowId);
		if(trl==null)
			return null;
		else{
			doms[0]= trl;
			doms[1] = trr;
		}
		return doms;
	}
	this.getRowById = function(rId){
		var rows = oThis.rows;
		for(var i=0;i<rows.length;i++){
			if(rows[i]._rId == rId) return rows[i];
		}
		return null;
	}
	this.getSelectedRowsValue = function(colNames){
		rows = oThis.getSelectedRows();
		for(var i=0;i<rows.length;i++){
			var row = rows[i];
			rows[i] = row.rowData;
		}
		if(colNames==null)return rows;
		else{
			var r = [];
			for(var i=0;i<rows.length;i++){
				r[i] = {};
				for(var j=0;j<colNames.length;j++){
					var o = r[i];
					o.s$(colNames[j],rows[i].p$(colNames[j]));
				}
			}
			return r;
		}
	}
	this.getValue = function(){
		var value = []; 
		var rows = oThis.rows;
		for(var i=0;i<rows.length;i++)
			value.push(rows[i].rowData);
		return value;
	}
	
	this.loadFirstPage = function(){
		var control = oThis.getPageCtl();
		if(control!=null){
			control.loadPage();
		}
	}
	this.bindData = function(data){
		//oThis.status("绑定数据...");
		oThis._rIndex = 0;		//初始化行号
		oThis.rows = [];
		for(var i=0;i<data.length;i++)	oThis.rows[i] = new SigmaRow(oThis,data[i],i);
		if(oThis.context.aggregate!=null && oThis.context.aggregate.length>0)
			oThis.aggRow = new SigmaAggRow(oThis);
		oThis.resetScroll();
		oThis.paintRows(0);
		if(oThis.getScrollBox().scrollTop!=0){
			oThis._notRepAfterScroll = true;
			oThis.getScrollBox().scrollTop = 0;
		}
		//oThis.status("绑定数据完成！");
	}
	oThis.resetLayout();
	oThis.paintHeader();
	this.getColByName = function(name){
		var cols = oThis.leafCols;
		for(var i=0;i<cols.length;i++){	if(cols[i].name === name)return cols[i];}
		return null;
	}
	this.getCurrentColWidth = function(col){
		var rightHead = oThis.getRightHead();
		var colgroup = u.$$(rightHead,"colgroup_"+oThis.id);
		var c = u.$$(colgroup,"col_"+col.name);
		return c.width;
	}
	this.getResizeObj = function(colName){
		var rightHead = oThis.getRightHead();
		var obj = u.$$(rightHead,"resize_"+colName);
		return obj;
	}
	this.endResize = function(col){
		var rBody = oThis.getRightBody();
		var cb = u.$$(rBody,"col_"+col.name);
		cb.width = col.width;
		var spane = oThis.getScrollPane();
		spane.style.width = oThis.countRightWidth();
	}
	this.selectAll = function(selected){
		//oThis.status("正在设置全选状态...");
		var rows = oThis.rows;
		for(var i=0;i<rows.length;i++){rows[i]._selected = selected;rows[i].buf=null;}
		var leftTb = oThis.getLeftTb();
		var rightTb = oThis.getRightTb();
		var rs = leftTb.rows;
		var cname = (selected==true?"selected":"");
		for(var i=0;i<rs.length;i++){
			if(i<rs.length-1){
				rs[i].cells[0].childNodes[0].checked = selected;
				rs[i].className = cname;
				rightTb.rows[i].className = cname;
			}else if(oThis.context.aggregate==null || oThis.context.aggregate.length<1){
				rs[i].cells[0].childNodes[0].checked = selected;
				rs[i].className = cname;
				rightTb.rows[i].className = cname;
			}
		}
		//oThis.status("设置全选状态 完成！");
	}
	this.comparator = function(o1,o2){
		var col = oThis.currentSortCol;
		var v1 = o1.getCellValue(col);
		var v2 = o2.getCellValue(col);
		var r = 0;
		if(v1==null && v2!=null) r=-1;
		else if(v1==null && v2==null) r=0;
		else if(v1!=null && v2==null) r=1;
		else if(col.mode=="number"){
			if(isNaN(v1)&& isNaN(v2)) r=0;
			else if(isNaN(v1) && !isNaN(v2)) r=-1;
			else if(!isNaN(v1) && isNaN(v2)) r=1;
			else if(v1>v2) r=1;
			else if(v1<v2) r=-1;
			else r = 0;
		}else if(col.mode=="boolean"){
			if(v1>v2) r=1;
			else if(v1==v2) r=0;
			else r=-1;
		}else r = v1.localeCompare(v2);
		
		if(col._order=="asc") return r;
		else return 0-r;
	}
	this.isSortable = function(col){
		if(col.sortable==null){
			if(oThis.context.sortable==null)return false;
			else return true;
		}
		return col.sortable;
	}
	this.sortByCol = function(column){
		if(oThis.isSortable(column)==false){
			alert("当前列不能排序!"); return ;
		}
		if(column._order=="asc"){
			column._order = "desc";
		}else{
			column._order = "asc";
		}
		oThis.currentSortCol = column;
		var rows=oThis.rows.sort(oThis.comparator);
		oThis.bindData(oThis.getValue());
	}
	
	this.blurCell = function(td){
		var s = td.id.split('@');
		var row = oThis.getRowById(s[1]);
		
		if(!row) return;
		
		var cell = row.cells()[s[2]];
		oThis._focusedCell = null;		//焦点td = null
		try{
  		if(td.isEditor==true){			//从编辑器离开
  			input = td.childNodes[0]
  			var col = cell.col;
  			if(col.mode==="boolean") cell.setValue(input.checked,true);
  			else cell.setValue(input.value.trim(),true);
  		}else{
  			td.childNodes[0].className = "";
  			oThis._focusHandle.blur();
  			td.childNodes[0].removeChild(oThis._focusHandle);	//移除只读单元格的焦点控制器
  		}
		}catch(e){}
		oThis._focusHandle = null;		//焦点处理器 = null
	}
	
	this.focusNextCell = function(td,d){
		oThis.blurCell(td);
		var s = td.id.split('@');
		var row = oThis.getRowById(s[1]);
		var cell = row.cells()[s[2]];
		if(d=="v"){						//纵向
			var nextRID = row._index+1;
			if(nextRID>=oThis.rows.length) {
				alert("没有下一行");return;
			}else{
				var nextRow = oThis.rows[nextRID];
				var nextCell = nextRow.cells()[cell.col.name];
				var nextTd = nextCell.getElement();
				if(nextTd!=null){
					if(oThis.getPaintMode()=="all"){
						if((nextRow._index * oThis.cellHeight-oThis.getScrollBox().scrollTop)/oThis.cellHeight>oThis.getVisRowsAmount()){
							oThis.setRow2Top(nextRow);
						}
					}
					oThis.focusCell(nextTd);
				}else{
					oThis.setRow2Top(nextRow);
					nextTd = nextRow.cells()[cell.col.name].getElement();
					oThis.focusCell(nextTd);
				}
			}
		}else if(d=="h"){				//横向
			var nextCol = oThis.getNextColumn(cell.col);
			if(nextCol==null){
				nextCol=oThis.leafCols[0];
				if(row._index+1>=oThis.rows.length){
					alert("没有下一行");return;
				}
				row = oThis.rows[row._index+1];
				oThis.getScrollBox().scrollLeft = 0;
			}
			var nextCell = row.cells()[nextCol.name];
			var nextTd = nextCell.getElement();
			if(nextTd!=null){
				if(oThis.getPaintMode()=="all"){
					if((row._index * oThis.cellHeight-oThis.getScrollBox().scrollTop)/oThis.cellHeight>oThis.getVisRowsAmount()){
						oThis.setRow2Top(row);
					}
				}
				oThis.focusCell(nextTd);
			}else{
				oThis.setRow2Top(row);
				nextTd = row.cells()[nextCell.col.name].getElement();
				oThis.focusCell(nextTd);
			}
			oThis.getRightTb().style.left = 0;
		}
	}
	this.getNextColumn = function(col){
		if(col.colIndex==oThis.leafCols.length-1) return null;
		else return oThis.leafCols[col.colIndex+1];
	}
	this.addRow = function(rowData){
		if(rowData==null) rowData = {};
		var row = new SigmaRow(oThis,rowData,oThis.rows.length);
		oThis.rows[oThis.rows.length]=row;
		oThis.resetScroll();
		oThis.setRow2Top(row);
		if(oThis.getPaintMode()=="all"){
			row.paint2Table();
		}
	}
	
	this.deleteRows = function(no){
		if(!no) return;
		if(!no.length) return;
		
		for(var i=no.length-1;i>=0;i--){
  		if(!no[i]) return;
  		var row = oThis.getRowById(no[i]);
  		if(!row) continue;
			row.removeElements();
			oThis.rows.remove(row);
    }
    
		rows = oThis.rows;
		for(var i=0;i<rows.length;i++){	
			var row = rows[i];	
			row._index = i;
			row.buf = null;
		}
		
    var leftTb = oThis.getLeftTb();
		var rs = leftTb.rows;
		if(oThis.context.sequence==true){
			var sqIndex = 0;
			if(oThis.context.radioBox==true ||oThis.context.checkBox==true)sqIndex++;
			for(var i=0;i<rs.length;i++){
				var row = oThis.getRowById(rs[i].id);
				if(i<rs.length-1){
					rs[i].cells[sqIndex].innerHTML = row._index+1;
				}else if(oThis.context.aggregate==null || oThis.context.aggregate.length<1){
					rs[i].cells[sqIndex].innerHTML = row._index+1;
				}
			}
		}
		if(rs.length<oThis.rows.length){
			var from = oThis.from;
			if(from + oThis.getVisRowsAmount()>oThis.rows.length)
				from = oThis.rows.length-oThis.getVisRowsAmount();
			if(from<0) from = 0;
			if(oThis.from==from )
				oThis.paintRows(from);
			else
				oThis.getScrollBox().scrollTop = from * oThis.cellHeight;
		}
		oThis.resetScroll();
	}
	

	this.deleteSelectedRows = function(){
		var rows = this.getSelectedRows();
		for(var i=0;i<rows.length;i++){
			rows[i].removeElements();
			oThis.rows.remove(rows[i]);
		}
		rows = oThis.rows;
		for(var i=0;i<rows.length;i++){	
			var row = rows[i];	
			row._index = i;
			row.buf = null;
		}
		var leftTb = oThis.getLeftTb();
		var rs = leftTb.rows;
		if(oThis.context.sequence==true){
			var sqIndex = 0;
			if(oThis.context.radioBox==true ||oThis.context.checkBox==true)sqIndex++;
			for(var i=0;i<rs.length;i++){
				var row = oThis.getRowById(rs[i].id);
				if(i<rs.length-1){
					rs[i].cells[sqIndex].innerHTML = row._index+1;
				}else if(oThis.context.aggregate==null || oThis.context.aggregate.length<1){
					rs[i].cells[sqIndex].innerHTML = row._index+1;
				}
			}
		}
		if(rs.length<oThis.rows.length){
			var from = oThis.from;
			if(from + oThis.getVisRowsAmount()>oThis.rows.length)
				from = oThis.rows.length-oThis.getVisRowsAmount();
			if(from<0) from = 0;
			if(oThis.from==from )
				oThis.paintRows(from);
			else
				oThis.getScrollBox().scrollTop = from * oThis.cellHeight;
		}
		oThis.resetScroll();
	}
	


	this.setRow2Top = function(row){
		var from = row._index; var totalRow = oThis.rows.length;
		if(from>totalRow-oThis.getVisRowsAmount())
			from = totalRow-oThis.getVisRowsAmount();
		if(from<0) from=0;
		if(oThis.getPaintMode()!="all"){
			oThis.paintRows(from);
			oThis._notRepAfterScroll = true;
		}
		oThis.getScrollBox().scrollTop = from * oThis.cellHeight;
	}
	this.onCellClicked = function(evt){}
	this.focusCell = function(td,triggerClickEvt){
		if(td==oThis._focusedCell) return;
		if(oThis._focusedCell!=null) oThis.blurCell(oThis._focusedCell);
		var s = td.id.split('@');
		var row = oThis.getRowById(s[1]);
		var cell = row.cells()[s[2]];
		var ro = cell.isReadonly();
		var rightX = td.offsetLeft+td.offsetWidth;
		var leftX = td.offsetLeft;
		if(triggerClickEvt==true){
			var evt = new Object();
			evt.cell = cell;
			oThis.onCellClicked(evt);
		}
		if(cell.isRightColumn()){
			var scrollBox = oThis.getScrollBox();
			var visLeftX = scrollBox.scrollLeft;
			var visRightX = scrollBox.scrollLeft + scrollBox.clientWidth-17;
			if(visRightX<rightX)
				scrollBox.scrollLeft = scrollBox.scrollLeft+(rightX-visRightX);
			if(visLeftX>leftX)
				scrollBox.scrollLeft = scrollBox.scrollLeft-(visLeftX-leftX);
		}
		
		oThis._focusedCell = td;
		var div = td.childNodes[0];
		if(ro===true){
			oThis._focusedCell.isEditor = false;
			div.className = "focused";
			div.innerHTML ="<input onkeydown='s_grid_cellFocusHandle("+oThis.id+",this.parentNode.parentNode,event);' style='width:0px;height:0px;border-width:0px;'/>"
				+div.innerHTML;
			var input = div.childNodes[0];
			window._toFocusDom = input;
			setTimeout("sgrid_focusdom()",20);
			oThis._focusHandle = input;
		}else{
			oThis._focusedCell.isEditor = true;
			cell.paintEditor(td);
			window._toFocusDom = td.childNodes[0];
			setTimeout("sgrid_focusdom()",20);
		}
	}
	
	this.onRowSelected = function(){}
	this.onCellValueChanged = function(){}
	//oThis.status("表格初始化完成！");


}
function s_grid_cellBlur(gridId,td,evt){
	var grid = SigmaUtil.retrieve(gridId);
	grid.blurCell(td);
}

function sgrid_focusdom(){
	try{
	  window._toFocusDom.focus();
	  window._toFocusDom.select();
	}catch(e){}
}
function s_grid_paint(gridId,from){
	var grid = SigmaUtil.retrieve(gridId);
	if(s_grid_paintTimer!=null)	clearTimeout(s_grid_paintTimer);
	s_grid_paintTimer = setTimeout('grid.paintRows('+from+')',30);
}

function s_grid_headCheckAll(gridId,checked){
	var u = SigmaUtil;
	var grid = u.retrieve(parseInt(gridId));
	grid.selectAll(checked);
}
function s_grid_onRowCheck(gridId,rowId,checked){
	var grid = SigmaUtil.retrieve(gridId);
	var row = grid.getRowById(rowId);
	if(row==null) return;
	row.setSelected(checked);
	var event = new Object();
	event.row = row;
	event.selected = checked;
	grid.onRowSelected(event);
}
function s_grid_onRowRadioCheck(gridId,rowId,checked){
	var grid = SigmaUtil.retrieve(parseInt(gridId));
	var row = grid.getRowById(rowId);
	if(row==null) return;
	row.setSelected(checked);
	
	var event = new Object();
	event.row = row;
	event.selected = checked;
	grid.onRowSelected(event);
}
function s_grid_cellFocusHandle(gridId,td,evt){
	var grid = SigmaUtil.retrieve(gridId);
	var keyCode = evt.keyCode||evt.which||evt.charCode;
	if(keyCode==9){
		grid.focusNextCell(td,"h");
	}else if(keyCode==13){
		grid.focusNextCell(td,"v");
	}
}
function s_grid_cellOnClick(gId,td,evt){
	var grid = SigmaUtil.retrieve(gId);
	grid.focusCell(td,true);
}

function s_grid_sortCol(gridId,colName){
	var grid = SigmaUtil.retrieve(gridId);
	grid.sortByCol(grid.getColByName(colName));
}

var s_grid_paintTimer = null;
function s_grid_onScroll(gridId,scrollLeft,scrollTop){
	var u = SigmaUtil;
	var grid = u.retrieve(gridId);
	if(scrollLeft!=grid.scrollLeft){
		var rHead = grid.getRightHead();
		var rightHeadTb = u.$$(rHead,"tLeftHead_"+grid.id);
		rightHeadTb.style.left = -grid.countLeftWidth()-scrollLeft;
		var rBody = grid.getRightBody();
		var rightTb = u.$$(rBody,"dataTable");
		rightTb.style.left=-scrollLeft;
		grid.scrollLeft = scrollLeft;
	}else if(grid.scrollTop !=scrollTop){
		grid.scrollTop = scrollTop;
		if(grid._notRepAfterScroll){grid._notRepAfterScroll=false;return;}
		if(grid.getPaintMode()=="all"){
			var lBody = grid.getLeftBody();
			var rBody = grid.getRightBody();
			var lTb = u.$$(lBody,"dataTable");
			var rTb = u.$$(rBody,"dataTable");
			lTb.style.top = -scrollTop; rTb.style.top =-scrollTop;
		}else{
			var from = scrollTop / grid.cellHeight;
			from = Math.round(from);
			s_grid_paint(gridId,from);
		}
	}
}
function s_grid_resize(gridId,colName,evt){
	var grid = SigmaUtil.retrieve(gridId);
	var startX = 0;
	var col = grid.getColByName(colName);
	var oldWidth = col.width;
	var beginWidth = grid.getCurrentColWidth(col);
	startX = evt.clientX;
	var obj =grid.getResizeObj(colName);
	s_draggingObj = obj;
	obj.moveTo = function(x,y){
		var offsetX = x-startX;
		var newWidth = parseInt(beginWidth) + offsetX;
		if(newWidth<10)newWidth = 10;
		grid.setColWidth(col,newWidth);
		//col.width = oldWidth;
	}
	obj.release = function(){
		grid.endResize(col);
		col.width = oldWidth;
	}
}
var s_draggingObj = null;
if(SigmaUtil.isIE()){
	window.document.attachEvent("onmousemove",
		function(e){if(s_draggingObj!=null)	s_draggingObj.moveTo(e.clientX,e.clientY);}
	);
	window.document.attachEvent("onmouseup",
		function(e){if(s_draggingObj!=null){s_draggingObj.release();s_draggingObj = null;}}
	);
}else{
	window.document.addEventListener("mousemove",
		function(e){if(s_draggingObj!=null)s_draggingObj.moveTo(e.pageX,e.pageY);},
		false
	);
	window.document.addEventListener("mouseup",
		function(e){if(s_draggingObj!=null)s_draggingObj = null;},
		false
	);
}



/*****************************************************/
/*			   以下代码属于分页控件						 */
/*****************************************************/

function SigmaPage(element,initInfo,grid){
	var u = SigmaUtil;
	u.register(this);
	this.pageSize = initInfo.pageSize;
	this.callback = initInfo.callback;
	this.grid = grid;
	if(typeof(element)=="string") element = u.$(element);
	this.element = element;
	var oThis = this;
	this.element.className = "SigmaPage";
	var sb = [];
	sb.push('<div class="last" onclick="s_page_onLast('+this.id+')"></div>');
	sb.push('<div class="next" onclick="s_page_onNext('+this.id+')"></div>');
	sb.push('<div class="info" id="info"></div>');
	sb.push('<div class="pre" onclick="s_page_onPre('+this.id+')"></div>');
	sb.push('<div class="first" onclick="s_page_onFirst('+this.id+')"></div>');
	this.element.innerHTML = sb.join("");
	
	this.loadPage = function(){
		if(oThis.page==null){
			oThis.page = {"index":0,"elements":[],"total":1}
		 	oThis.page.index =0;
		 	oThis.page.elements = [];
		 	oThis.page.total = 1;
		}
		var page = null;
		if(typeof(oThis.callback)=="string"){
			var url = oThis.callback +(oThis.callback.indexOf("?")>0?"?":"&")+ "size=" + oThis.size + "&from=" + oThis.page.index;
			//TODO:调用ajax从url获得数据
		}else{
			page = oThis.callback.getPage(oThis);
		}
		oThis.setPage(page);
		grid.bindData(page.elements);
	}
	
	this.toFirst = function(){
		oThis.page.index = 0;
		oThis.loadPage();
	}
	this.toPre = function(){
		if(oThis.page.index<=0) return;
		oThis.page.index --;
		oThis.loadPage();
	}
	this.toNext = function(){
		if(oThis.page.index>=oThis.page.pageAmount-1) return;
		oThis.page.index ++;
		oThis.loadPage();
	}
	this.toLast = function(){
		oThis.page.index = oThis.page.pageAmount-1;
		oThis.loadPage()
	}
	this.setPage = function(page){
		var pageAmount = 1;
		if(page.total!=0){
			pageAmount = page.total/oThis.pageSize;
			pageAmount = Math.round(pageAmount);
			if(pageAmount*oThis.pageSize<page.total)
				pageAmount++;
		}
		page.pageAmount = pageAmount;
		
		oThis.page = page;
		var info = u.$$(this.element,"info");
		info.innerHTML = (oThis.page.index+1)+"/"+oThis.page.pageAmount;
	}
}

function s_page_onFirst(id){
	var pageCtl = SigmaUtil.retrieve(id);
	pageCtl.toFirst();
}

function s_page_onPre(id){
	var pageCtl = SigmaUtil.retrieve(id);
	pageCtl.toPre();
}
function s_page_onNext(id){
	var pageCtl = SigmaUtil.retrieve(id);
	pageCtl.toNext();
}
function s_page_onLast(id){
	var pageCtl = SigmaUtil.retrieve(id);
	pageCtl.toLast();
}


function SigmaTree(parent,context,root){
	var u = SigmaUtil;
	this.context = context;
	this.focusedNode = null;
	var oThis = this;
	if(parent.constructor == String) parent = u.$(parent);
	parent.className = "SigmaTree";
	u.register(this);
	var roots = [];
	this.children = [];
	this.element = parent;
	
	if((root instanceof Array)==false){
		roots.push(root);
	}else
		roots.addAll(root);
	
	var buildNodes = function(datas,np){
		var nodes = [];
		for(var i=0;i<datas.length;i++){
			var data = datas[i];
			var node = new SigmaTreeNode(data);
			if(data.children!=null && data.children.length>0){
				node.children = buildNodes(data.children,node);
			}
			node.parent = np;
			nodes.push(node);
		}
		return nodes;
	}
	this.children = buildNodes(roots,oThis);
	for(var i=0;i<this.children.length;i++){
		this.children[i]
		this.children[i].paint();
	}
	this.getIterator = function(rootFirst){
		if(rootFirst==true){
			return new SigmaTreeFirstIterator(oThis);
		}else
			return new SigmaTreeLastIterator(oThis);
	}

	this.add = function(data,parent){
		var node = new SigmaTreeNode(data);
		if(parent==null){
			oThis.children.push(node);
			node.parent = oThis;
			node.paint();
		}else{
			parent.addChild(node);
		}
	}

	this.remove = function(node){
		node.remove();
		if(oThis.focusedNode==node)
			oThis.focusedNode = null;
	}

	this.setFocused = function(node){
		node.focused = true;
		oThis.focusedNode = node;
	}

	this.getValue = function(v){
		if(oThis.children==null ||oThis.children.length==0)
			return null;
		
		if(v==null)	v = true;
		var value = [];
		for(var i=0;i<oThis.children.length;i++){
			var c = oThis.children[i];
			value.push(c.getValue(v));
		}
		return value;
	}

	this.onClicked = function(){}
	this.onChanged = function(){}
}
function SigmaTreeLastIterator(tree){
	var current = tree;
	var oThis = this;
	this.next  = function(){
		if(current==tree){
			if(tree.children!=null && tree.children.length>0){
				current = oThis.getLeaf(tree.children[0]);
			}else current = null;
		}else{
			var b = oThis.getNextBrother(current);
			if(b==null){
				current = current.parent;
				if(current == tree)
					current = null;
			}else current = oThis.getLeaf(b);
		}
		return current;
	}
	this.getLeaf = function(node){
		if(node.hasChildren()==true){
			return oThis.getLeaf(node.children[0]);
		}else
			return node;
	}
	this.getNextBrother = function(current){
		var brothers = current.parent.children;
		var index = brothers.indexOf(current);
		if(index<brothers.length-1){
			return brothers[index+1];
		}else return null;
	}

}

function SigmaTreeFirstIterator(tree){
	var current = tree;
	var oThis = this;
	
	this.visitAll = function(visitor){
	}

	this.next = function(){
		var children = current.children;
		if(children!=null && children.length>0){
			current =children[0];
		}else{
			if(current==tree)
				current = null;
			else
				current = oThis.getNextBrother(current);
		}
		return current;
	}

	this.getNextBrother = function(current){
		var brothers = current.parent.children;
		var index = brothers.indexOf(current);
		if(index<brothers.length-1){
			return brothers[index+1];
		}else{
			if(current.parent.constructor==SigmaTree){
				return null;
			}else{
				return oThis.getNextBrother(current.parent);
			}
		}
	}
	
}

function SigmaTreeNode(data){
	this.data = data;
	this.parent = null;
	this.children = null;
	this.state = "closed";
	this.focused = false;
	var u = SigmaUtil;
	u.register(this);
	var oThis = this;
	
	this.getTree = function(){
		if(oThis.parent.constructor == SigmaTree)
			return oThis.parent;
		else 
			return oThis.parent.getTree();
	}
	
	this.getCanvas = function(){
		var parent = oThis.parent;
		var canvas = null;
		if(parent.constructor == SigmaTree){
			canvas =  parent.element;
		}else{
			canvas = parent.getChildrenBox();
		}
		return canvas;
	}

	
	
	
	this.hasChildren = function(){
		if(oThis.children!=null && oThis.children.length>0)
			return true;
		else 
			return false;
	}
	this.isLast = function(){
		var index = oThis.parent.children.indexOf(oThis);
		if(index==oThis.parent.children.length-1)
			return true;
	}
	this.getElement = function(){
		var e = u.$$(oThis.getCanvas(),"node_"+oThis.id);
		return e;
	}
	this.remove = function(){
		oThis.getElement().removeNode(true);
		oThis.parent.children.remove(oThis);
		oThis.parent = null;
		oThis.children = null;
	}
	this.getChildrenBox = function(){
		var e = u.$$(oThis.getCanvas(),"child_"+oThis.id);
		return e;
	}
	
	this.getTitleBox = function(){
		var e = u.$$(oThis.getCanvas(),"title_"+oThis.id);
		return e;
	}

	this.paintHead = function(node){
		var sb = [];
		var className = "";
		var evtStr = "";
		if(node==null){
			evtStr = "onclick='s_tree_onState("+oThis.id+");'";
			if(oThis.hasChildren()){
				if(oThis.isLast()){
					if(oThis.state=="opened"){
						className="minus_l";
					}else{
						className="plus_l";
					}
				}else{
					if(oThis.state=="opened"){
						className="minus";
					}else
						className="plus";
				}
			}else{
				if(oThis.isLast()){
					className="hr_l";
				}else{
					className="hr";
				}
			}
			node = oThis;
		}else{
			
			if(node.isLast())
				className = "blank";
			else
				className = "vertical";
		}
		sb.push("<div class='"+className+"' ");
		sb.push( evtStr);
		sb.push("></div>");
		if(node.parent.constructor==SigmaTreeNode)
			sb.splice(0,0,oThis.paintHead(node.parent));
		return sb.join("");
	}
	 
	this.paint = function(){
		var element = oThis.getElement();
		if(element ==null){
			element = document.createElement("div");
			element.id = "node_"+oThis.id;
			element.className = "Node";
			oThis.getCanvas().appendChild(element);
			var sb = [];
			sb.push("<div class='title' id='title_"+oThis.id);
			sb.push("' onmouseover='s_tree_onmouseover("+oThis.id+")'");
			sb.push(" onmouseout='s_tree_onmouseout("+oThis.id+")'");
			sb.push(" onclick='s_tree_onclick("+oThis.id+")'");
			sb.push(">"+oThis.data["name"]);
			sb.push("</div>");
			var head = oThis.paintHead();
			sb.splice(0,0,head);
			element.innerHTML = sb.join("");
			var items = element.childNodes;
			var len = 2;
			for(var i=0;i<items.length;i++){
				var item = items.item(i);
				if(item.className=="title")
					len += oThis.data["name"].asciiLen()*6+4;
				else
					len += 19;
			}
			element.style.width = len;
		}else{
		
		}
	}
	this.close = function(){
		var childrenBox = oThis.getChildrenBox();
		if(childrenBox !=null){
			childrenBox.style.display = "none";
		}
		var element  = oThis.getElement();
		var title = oThis.getTitleBox();
		var index = oThis.indexOf(element.childNodes,title);
		var head = element.childNodes.item(index-1);
		if(oThis.isLast()){
			head.className = "plus_l";
		}else {
			head.className = "plus";
		}
		oThis.state = "closed";
	}
	this.open = function(){
		var element = oThis.getElement();
		var title = oThis.getTitleBox();
		var index = oThis.indexOf(element.childNodes,title);
		var head = element.childNodes.item(index-1);
		if(oThis.isLast()){
			head.className = "minus_l";
		}else {
			head.className = "minus";
		}
		oThis.state = "opened";

		var childrenBox = oThis.getChildrenBox();
		if(childrenBox !=null){
			childrenBox.style.display = "";
			return;
		}
		
		var brothers = element.parentNode.childNodes;
		var index = oThis.indexOf(brothers,element);
		var canvas = oThis.getCanvas();
		
		childrenBox = document.createElement("div");
		childrenBox.id = "child_"+oThis.id;
		childrenBox.className = "childrenBox";
		if(index == brothers.length-1){
			canvas.appendChild(childrenBox);
		}else{
			canvas.insertBefore(childrenBox,brothers.item(index+1));
		}
		for(var i=0;i<oThis.children.length;i++){
			var child = oThis.children[i];
			child.paint();
		}
	}

	this.indexOf = function(collection,element){
		for(var i=0;i<collection.length;i++){
			var one = collection.item(i);
			if(one===element)
				return i;
		}
		return -1;
	}
	
	this.changeState = function(){
		if(oThis.hasChildren()==false)
			return;
		if(oThis.state=="closed"){
			oThis.open();
		}else{
			oThis.close();
		}
	}
	this.onfocus = function(){
		oThis.getTitleBox().className = "focus";
		var tree = oThis.getTree();
		var old = tree.focusedNode;
		
		oThis.focused = true;
		tree.focusedNode = oThis;
		if(old!=null){
			if(old!=oThis){
				old.focused = false;
				old.getTitleBox().className = "title";
				tree.onChanged();
			}
		}else
			tree.onChanged();
	}

	this.getValue = function(withChild){
		var v = oThis.data;
		v.children = null;
		if(withChild==true){
			var cData = null;
			if(oThis.hasChildren()){
				cData = [];
				var children = oThis.children;
				for(var i=0;i<children.length;i++){
					var child = children[i];
					var cv = child.getValue(true);
					cData.push(cv);
				}
			}
			v.children = cData;
		}else{
			v.children = null;
		}
		return v;
	}
}

function s_tree_onState(nodeId){
	var node = SigmaUtil.retrieve(nodeId);
	node.changeState();
}

function s_tree_onmouseover(nodeId){
	var node = SigmaUtil.retrieve(nodeId);
	if(node.focused==false)
		node.getTitleBox().className = "mover";
	else{
		node.getTitleBox().className = "focus";
	}
}

function s_tree_onmouseout(nodeId){
	var node = SigmaUtil.retrieve(nodeId);
	if(node.focused==false)
		node.getTitleBox().className = "title";
	else{
		node.getTitleBox().className = "focus";
	}
}

function s_tree_onclick(nodeId){
	var node = SigmaUtil.retrieve(nodeId);
	node.onfocus();
	node.getTree().onClicked();
}


